package com.itlong.cloud.controller.upgrade;

import com.itlong.cloud.POJO.DTO.operate.*;
import com.itlong.cloud.POJO.PO.OperateUserInfoPO;
import com.itlong.cloud.POJO.VO.MessageVO;
import com.itlong.cloud.POJO.VO.operate.DeviceTypeDefineVO;
import com.itlong.cloud.POJO.VO.operate.OperateOSSTokenVO;
import com.itlong.cloud.POJO.VO.operate.OperateProductTypeVO;
import com.itlong.cloud.annotation.AuthAccessRequired;
import com.itlong.cloud.annotation.LoggerInfo;
import com.itlong.cloud.annotation.UnAuthAccessRequired;
import com.itlong.cloud.annotation.UnParamEncrypt;
import com.itlong.cloud.constants.LogDescConstant;
import com.itlong.cloud.controller.system.OperateFunctionController;
import com.itlong.cloud.enumerate.ecode.BaseErrorCodeEnum;
import com.itlong.cloud.enumerate.ecode.OperateErrorCodeEnum;
import com.itlong.cloud.equip.operate.IOperatePackageServiceClient;
import com.itlong.cloud.iottp.IIotAliOSSServiceClient;
import com.itlong.cloud.project.operate.IOperateProductTypeServiceClient;
import com.itlong.cloud.project.operate.IOperateProjectServiceClient;
import com.itlong.cloud.thrown.DataAccessException;
import com.itlong.cloud.user.operate.IOperateUserInfoServiceClient;
import com.itlong.cloud.utils.network.http.HttpProtocolUtil;
import com.itlong.cloud.utils.page.Page;
import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.InputStream;
import java.util.List;

/**
 * <desc>
 *      运营-固件升级-安装包管理管理控制器
 * </desc>
 *
 * @createDate 2018/08/22
 */
@RestController
@RequestMapping("/upgrade/package")
public class OperatePackageController {
    private static final Logger LOG = LoggerFactory.getLogger(OperateFunctionController.class);

    @Autowired
    IOperateProjectServiceClient iOperateProjectServiceClient;

    @Autowired
    IIotAliOSSServiceClient iIotAliOSSServiceClient;

    @Autowired
    IOperatePackageServiceClient iOperatePackageServiceClient;

    @Autowired
    IOperateUserInfoServiceClient userInfoServiceClient;

    @Autowired
    IOperateProductTypeServiceClient iOperateProductTypeServiceClient;



    /**
     * <desc>
     *      分页查询产品型号简易信息
     * <desc/>
     *
     * @param pageDTO 分页查询条件
     * @return
     * @author Qiang.S
     * @createDate 2019-02-21
     */
    @UnAuthAccessRequired
    @RequestMapping(value = "/getPage", method = RequestMethod.POST)
    @ResponseBody
    public Object getPage(OperateProductTypeGetPageDTO pageDTO){
        try {
            HttpServletRequest request=((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
            pageDTO= HttpProtocolUtil.parseRequestParamToDTO(OperateProductTypeGetPageDTO.class,request);
            Page<OperateProductTypeVO> page = iOperateProductTypeServiceClient.getPage(pageDTO);
            MessageVO messageVO = new MessageVO(BaseErrorCodeEnum.SUCCESS.getErrorCode(), page);
            return  messageVO;
        }catch (Exception e){
            throw new DataAccessException("【运营_固件升级_产品型号getPage】查询产品型号失败", e);
        }
    }

    /**
     * <desc>
     *      分页获取安装包信息
     * <desc/>
     *
     * @param operateUpdateInfoGetPageDTO 查询参数DTO
     * @return
     * @author Qiang.S
     * @createDate 2018-08-23
     */
    @RequestMapping(value = "/getUpdateInfoPage", method = RequestMethod.POST)
    @ResponseBody
    @UnAuthAccessRequired
    public Object getUpdateInfoPage(OperateUpdateInfoGetPageDTO operateUpdateInfoGetPageDTO){
        MessageVO messageVO;
        try{
            HttpServletRequest request=((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
            operateUpdateInfoGetPageDTO= HttpProtocolUtil.parseRequestParamToDTO(OperateUpdateInfoGetPageDTO.class,request);
            //判断参数合法性
            if (null == operateUpdateInfoGetPageDTO) {
                return new MessageVO(BaseErrorCodeEnum.NOT_PARAM.getErrorCode());
            }
            messageVO=new MessageVO(BaseErrorCodeEnum.SUCCESS.getErrorCode(),
                    iOperatePackageServiceClient.getUpdateInfoPage(operateUpdateInfoGetPageDTO));
        }catch (Exception e){
            throw new DataAccessException("【运营_固件升级_分页获取安装包信息getUpdateInfoPage】分页获取安装包信息失败",e);
        }
        return messageVO;
    }

    /**
     * <desc>
     *      批量删除安装包信息
     * <desc/>
     *
     * @param updateIds 更新文件编号,逗号分隔
     * @param updateNames 文件名称,逗号分隔
     * @return
     * @author Qiang.S
     * @createDate 2018-08-23
     */
    @RequestMapping(value = "/deleteUpdateInfo", method = RequestMethod.POST)
    @AuthAccessRequired
    @LoggerInfo(operateDesc = LogDescConstant.PACKAGE_DELETE_LOG_DESC)
    @ResponseBody
    public Object deleteUpdateInfo( String updateIds, String updateNames,String token,String operateFunction,String operateWay){
        MessageVO messageVO;
        try{
            HttpServletRequest request= ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
            updateIds=request.getAttribute("updateIds")==null?null:request.getAttribute("updateIds").toString();
            updateNames=request.getAttribute("updateNames")==null?null:request.getAttribute("updateNames").toString();
            token=request.getAttribute("token")==null?null:request.getAttribute("token").toString();
            operateFunction=request.getAttribute("operateFunction")==null?null:request.getAttribute("operateFunction").toString();
            operateWay=request.getAttribute("operateWay")==null?null:request.getAttribute("operateWay").toString();

            if (StringUtils.isBlank(updateIds)){
                return new MessageVO(OperateErrorCodeEnum.PACKAGE_UPDATE_ID_EMPTY_ERR.getErrorCode());
            }
            if (StringUtils.isBlank(updateNames)){
                return new MessageVO(OperateErrorCodeEnum.PACKAGE_UPDATE_NAME_EMPTY_ERR.getErrorCode());
            }
            if (StringUtils.isBlank(token)){
                return new MessageVO(OperateErrorCodeEnum.LACK_OF_PARAMETER.getErrorCode());
            }
            if (StringUtils.isBlank(operateFunction)){
                return new MessageVO(OperateErrorCodeEnum.LACK_OF_PARAMETER.getErrorCode());
            }
            if (StringUtils.isBlank(operateWay)){
                return new MessageVO(OperateErrorCodeEnum.LACK_OF_PARAMETER.getErrorCode());
            }
            OperateUserInfoPO user=userInfoServiceClient.retrieve(token);
            String ip = HttpProtocolUtil.getIpAddr(request);
            iOperatePackageServiceClient.deleteUpdateInfo(updateIds,user.getUserId(),operateFunction,operateWay,updateNames,ip);
            iIotAliOSSServiceClient.deleteFile(updateNames);
            messageVO=new MessageVO(updateIds, BaseErrorCodeEnum.SUCCESS.getErrorCode());
        }catch (Exception e){
            throw new DataAccessException("【运营_固件升级_删除安装包信息deleteUpdateInfo】删除安装包信息失败",e);
        }
        return messageVO;
    }





    /**
     * <desc>
     *      根据安装包名称查询结果
     * <desc/>
     *
     * @param updateName 文件名称
     * @return
     * @author Qiang.S
     * @createDate 2018-10-09
     */
    @RequestMapping(value = "/getUpdateInfoByName", method = RequestMethod.POST)
    @ResponseBody
    public Object getUpdateInfoByName(String updateName){
        MessageVO messageVO;
        try{
            HttpServletRequest request= ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
            updateName=request.getAttribute("updateName")==null?null:request.getAttribute("updateName").toString();
            if (StringUtils.isBlank(updateName)){
                return new MessageVO(OperateErrorCodeEnum.PACKAGE_UPDATE_NAME_EMPTY_ERR.getErrorCode());
            }
            messageVO=new MessageVO(BaseErrorCodeEnum.SUCCESS.getErrorCode(),(Object) iOperatePackageServiceClient.getUpdateInfoByName(updateName));
        }catch (Exception e){
            throw new DataAccessException("【运营_固件升级_根据名称查询结果getUpdateInfoByName】根据名称查询结果",e);
        }
        return messageVO;
    }

    /**
     * <desc>
     *      获取安装包详细信息
     * <desc/>
     *
     * @param updateId 更新文件编号
     * @return
     * @author Qiang.S
     * @createDate 2018-08-23
     */
    @RequestMapping(value = "/getUpdateDetail", method = RequestMethod.POST)
    @ResponseBody
    @UnAuthAccessRequired
    public Object getUpdateDetail(String updateId){
        MessageVO messageVO;
        try{
            HttpServletRequest request= ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
            updateId=request.getAttribute("updateId")==null?null:request.getAttribute("updateId").toString();
            //判断参数合法性
            if (StringUtils.isBlank(updateId)){
                return new MessageVO(OperateErrorCodeEnum.PACKAGE_UPDATE_ID_EMPTY_ERR.getErrorCode());
            }
            messageVO=new MessageVO(BaseErrorCodeEnum.SUCCESS.getErrorCode(), iOperatePackageServiceClient.getUpdateDetail(updateId));
        }catch (Exception e){
            throw new DataAccessException("【运营_固件升级_获取安装包详细信息getUpdateDetail】获取安装包详细信息失败",e);
        }
        return messageVO;
    }

    
    /**
    *<desc>
    * 分页获取特殊操作日志
    *</desc>
    *
    * @Author  chengshican
    * @Date   2020-11-10 18:41
    * @Param  updateId 对应操作数据id(更新文件编号)
    * @Return      
    * @Exception   
    * 
    */
    @RequestMapping(value = "/getOperationSpecialLogList", method = RequestMethod.POST)
    @ResponseBody
    @UnAuthAccessRequired
    public Object getOperationSpecialLogList(String updateId, String pageSize, String currentPage, String orderColumn,String orderRule){
        MessageVO messageVO;
        try{
            HttpServletRequest request= ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
            updateId=request.getAttribute("updateId")==null?null:request.getAttribute("updateId").toString();
            pageSize=request.getAttribute("pageSize")==null?null:request.getAttribute("pageSize").toString();
            currentPage=request.getAttribute("currentPage")==null?null:request.getAttribute("currentPage").toString();
            orderColumn=request.getAttribute("orderColumn")==null?null:request.getAttribute("orderColumn").toString();
            orderRule=request.getAttribute("orderRule")==null?null:request.getAttribute("orderRule").toString();

            //判断参数合法性
            if (StringUtils.isBlank(updateId)){
                return new MessageVO(OperateErrorCodeEnum.PACKAGE_UPDATE_ID_EMPTY_ERR.getErrorCode());
            }
            messageVO=new MessageVO(BaseErrorCodeEnum.SUCCESS.getErrorCode(), iOperatePackageServiceClient.getOperationSpecialLogList(updateId,pageSize,currentPage,orderColumn,orderRule));
        }catch (Exception e){
            throw new DataAccessException("【运营_固件升级_获取分页获取特殊操作日志getOperationSpecialLogList】分页获取特殊操作日志信息失败",e);
        }
        return messageVO;

    }

    /**
     *<desc>
     * 获取特殊操作日志详情
     *</desc>
     *
     * @Author  chengshican
     * @Date   2020-11-10 18:41
     * @Param  log_id 逻辑ID
     * @Return
     * @Exception
     *
     */
    @RequestMapping(value = "/getOperationSpecialLogByLogId", method = RequestMethod.POST)
    @ResponseBody
    @UnAuthAccessRequired
    public Object getOperationSpecialLogByLogId(String logId){
        MessageVO messageVO;
        try{
            HttpServletRequest request= ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
            logId=request.getAttribute("logId")==null?null:request.getAttribute("logId").toString();

            //判断参数合法性
            if (StringUtils.isBlank(logId)){
                return new MessageVO(OperateErrorCodeEnum.PACKAGE_UPDATE_ID_EMPTY_ERR.getErrorCode());
            }
            messageVO=new MessageVO(BaseErrorCodeEnum.SUCCESS.getErrorCode(), iOperatePackageServiceClient.getOperationSpecialLogByLogId(logId));
        }catch (Exception e){
            throw new DataAccessException("【运营_固件升级_获取分页获取特殊操作日志getOperationSpecialLogList】分页获取特殊操作日志信息失败",e);
        }
        return messageVO;

    }
    /**
     * <desc>
     *      安装包信息更新(未更新安装文件时使用)
     * <desc/>
     *
     * @param operateUpdateUpdateInfoDTO 更新信息DTO
     * @return
     * @author Qiang.S
     * @createDate 2018-08-28
     */
    @RequestMapping(value = "/updateUpdateInfo", method = RequestMethod.POST)
    @LoggerInfo(operateDesc = LogDescConstant.PACKAGE_UPDATE_LOG_DESC)
    @ResponseBody
    public Object updateUpdateInfo(OperateUpdateUpdateInfoDTO operateUpdateUpdateInfoDTO){
        MessageVO messageVO;
        try{
            HttpServletRequest request=((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
            operateUpdateUpdateInfoDTO= HttpProtocolUtil.parseRequestParamToDTO(OperateUpdateUpdateInfoDTO.class,request);
            //判断参数合法性
            if (StringUtils.isBlank(operateUpdateUpdateInfoDTO.getUpdateId())){
                return new MessageVO(OperateErrorCodeEnum.PACKAGE_UPDATE_ID_EMPTY_ERR.getErrorCode());
            }
            if (StringUtils.isBlank(operateUpdateUpdateInfoDTO.getDeviceType())){
                return new MessageVO(OperateErrorCodeEnum.PACKAGE_DEVICE_TYPE_EMPTY_ERR.getErrorCode());
            }
            if (!"1".equals(operateUpdateUpdateInfoDTO.getDeviceType()) && StringUtils.isBlank(operateUpdateUpdateInfoDTO.getVersion())){
                return new MessageVO(OperateErrorCodeEnum.PACKAGE_VERSION_EMPTY_ERR.getErrorCode());
            }
            operateUpdateUpdateInfoDTO.setIp(HttpProtocolUtil.getIpAddr(request));
            OperateUserInfoPO user=userInfoServiceClient.retrieve(operateUpdateUpdateInfoDTO.getToken());
            operateUpdateUpdateInfoDTO.setLoginUserId(user.getUserId());
            iOperatePackageServiceClient.updateUpdateInfo(operateUpdateUpdateInfoDTO);
            messageVO=new MessageVO(operateUpdateUpdateInfoDTO.getUpdateId(), BaseErrorCodeEnum.SUCCESS.getErrorCode());
        }catch (Exception e){
            throw new DataAccessException("【运营_固件升级_分页获取安装包信息getUpdateInfoPage】分页获取安装包信息失败",e);
        }
        return messageVO;
    }

    
    /**
    *<desc>
    *   通过产品类型查询产品型号
    *</desc>
    *
    * @Author  chengshican
    * @Date   2020-11-11 16:07
    * @Param  deviceTypes
    * @Return      
    * @Exception   
    * 
    */
    @RequestMapping(path = "/getProductCodeByDeviceType" ,method = RequestMethod.POST)
    @ResponseBody
    public Object getProductCodeByDeviceType(String deviceTypes ){
        MessageVO messageVO;
        try{
            HttpServletRequest request=((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
            deviceTypes=request.getAttribute("deviceTypes")==null?null:request.getAttribute("deviceTypes").toString();
            //判断参数合法性
            if (StringUtils.isBlank(deviceTypes)){
                return new MessageVO(OperateErrorCodeEnum.NOT_PARAM.getErrorCode());
            }

            List<DeviceTypeDefineVO> deviceTypeList = iOperatePackageServiceClient.getProductCodeByDeviceType(deviceTypes);
            messageVO=new MessageVO(BaseErrorCodeEnum.SUCCESS.getErrorCode(),
                    deviceTypeList);
        }catch (Exception e){
            throw new DataAccessException("【获取产品型号getProductCodeByDeviceType】获取产品型号失败",e);
        }
        return messageVO;
    }

    /**
     * <desc>
     *      获取阿里OSS通行证
     * <desc/>
     *
     * @return
     * @author Qiang.S
     * @createDate 2018-07-13
     */
    @RequestMapping(value = "/getOSSToken", method = RequestMethod.POST)
    @ResponseBody
    public Object getOSSToken(String token){
        MessageVO messageVO;
        try{
            HttpServletRequest request=((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
            token=request.getAttribute("token")==null?null:request.getAttribute("token").toString();
            OperateUserInfoPO user=userInfoServiceClient.retrieve(token);
            OperateOSSTokenVO operateOSSTokenVO = iIotAliOSSServiceClient.getOSSToken();
            if (operateOSSTokenVO != null && user != null) {
                operateOSSTokenVO.setUserId(user.getUserId());
            }
            messageVO=new MessageVO(BaseErrorCodeEnum.SUCCESS.getErrorCode(),
                    operateOSSTokenVO);
        }catch (Exception e){
            throw new DataAccessException("【获取阿里OSS通行证getOSSTokenk】获取阿里OSS通行证失败",e);
        }
        return messageVO;
    }

    /**
     * <desc>
     *      阿里OSS回调入口
     * <desc/>
     *
     * @return
     * @author Qiang.S
     * @createDate 2018-07-12
     */
    @RequestMapping(value = "/OSSCallBack", method = RequestMethod.POST)
    @UnAuthAccessRequired
    @ResponseBody
    @UnParamEncrypt
    public void OSSCallBack(HttpServletRequest request, HttpServletResponse response){
        try {
            OperateOSSCallBackDTO operateOSSCallBackDTO = new OperateOSSCallBackDTO();
            operateOSSCallBackDTO.setAutorizationInput(new String(request.getHeader("Authorization")));
            operateOSSCallBackDTO.setContentLen(Integer.parseInt(request.getHeader("content-length")));
            operateOSSCallBackDTO.setOssCallbackBody(GetPostBody(request.getInputStream(), Integer.parseInt(request.getHeader("content-length"))));
            operateOSSCallBackDTO.setPubKeyInput(request.getHeader("x-oss-pub-key-url"));
            operateOSSCallBackDTO.setQueryString(request.getQueryString());
            operateOSSCallBackDTO.setUri(request.getRequestURI());
            String ip = HttpProtocolUtil.getIpAddr(request);
            operateOSSCallBackDTO.setIp(ip);
           // LOG.info("阿里OSS回调入口!=========》{}",operateOSSCallBackDTO.getOssCallbackBody().toString());
            boolean ref = iIotAliOSSServiceClient.OSSCallBack(operateOSSCallBackDTO);
            if (ref) {
                response(request, response, "{\"Status\":\"OK\"}", HttpServletResponse.SC_OK);

            }else {
                response(request, response, "{\"Status\":\"verdify not ok\"}", HttpServletResponse.SC_BAD_REQUEST);
            }
        }catch (Exception e){
            try {
                response(request, response, "{\"Status\":\"verdify not ok\"}", HttpServletResponse.SC_BAD_REQUEST);
            } catch (IOException e1) {
                e1.printStackTrace();
            }
            throw new DataAccessException("【阿里OSS回调OSSCallBack】阿里OSS回调处理失败", e);
        }
    }

    /**
     * <desc>
     *      阿里OSS回调入口
     * <desc/>
     *
     * @return
     * @author Qiang.S
     * @createDate 2018-07-12
     */
    @RequestMapping(value = "/mediaOSSCallBack", method = RequestMethod.POST)
    @UnAuthAccessRequired
    @ResponseBody
    @UnParamEncrypt
    public void mediaOSSCallBack(HttpServletRequest request, HttpServletResponse response){
        try {
            //LOG.info("后台移到运营这边的多媒体资源上传视频阿里OSS回调入口：" + request.getHeaderNames());
            OperateOSSCallBackDTO operateOSSCallBackDTO = new OperateOSSCallBackDTO();
            operateOSSCallBackDTO.setAutorizationInput(new String(request.getHeader("Authorization")));
            operateOSSCallBackDTO.setContentLen(Integer.parseInt(request.getHeader("content-length")));
            operateOSSCallBackDTO.setOssCallbackBody(GetPostBody(request.getInputStream(), Integer.parseInt(request.getHeader("content-length"))));
            operateOSSCallBackDTO.setPubKeyInput(request.getHeader("x-oss-pub-key-url"));
            operateOSSCallBackDTO.setQueryString(request.getQueryString());
            operateOSSCallBackDTO.setUri(request.getRequestURI());
            //LOG.info("后台移到运营这边的阿里OSS回调参数：" + operateOSSCallBackDTO);
            boolean ref = iIotAliOSSServiceClient.OSSMediaCallBack(operateOSSCallBackDTO);
            if (ref) {
                response(request, response, "{\"Status\":\"OK\"}", HttpServletResponse.SC_OK);
            }else {
                response(request, response, "{\"Status\":\"verdify not ok\"}", HttpServletResponse.SC_BAD_REQUEST);
            }
        }catch (Exception e){
            try {
                response(request, response, "{\"Status\":\"verdify not ok\"}", HttpServletResponse.SC_BAD_REQUEST);
            } catch (IOException e1) {
                e1.printStackTrace();
            }
            throw new DataAccessException("【阿里OSS回调OSSCallBack】阿里OSS回调处理失败", e);
        }
    }

    /**
     * <desc>
     *     组装阿里OSS回调response
     * </desc>
     *
     * @return
     * @author Qiang.S
     * @createDate 2018/07/12
     */
    private void response(HttpServletRequest request, HttpServletResponse response, String results, int status) throws IOException {
        String callbackFunName = request.getParameter("callback");
        response.addHeader("Content-Length", String.valueOf(results.length()));
        if (callbackFunName == null || callbackFunName.equalsIgnoreCase("")){
            response.getWriter().println(results);
        }
        else{
            response.getWriter().println(callbackFunName + "( " + results + " )");
        }
        response.setStatus(status);
        response.flushBuffer();
    }

    /**
     * <desc>
     *     获取阿里OSS中GetPostBody
     * </desc>
     *
     * @return
     * @author Qiang.S
     * @createDate 2018/07/11
     */
    private String GetPostBody(InputStream is, int contentLen) {
        if (contentLen > 0) {
            int readLen = 0;
            int readLengthThisTime = 0;
            byte[] message = new byte[contentLen];
            try {
                while (readLen != contentLen) {
                    readLengthThisTime = is.read(message, readLen, contentLen - readLen);
                    if (readLengthThisTime == -1) {// Should not happen.
                        break;
                    }
                    readLen += readLengthThisTime;
                }
                return new String(message);
            } catch (IOException e) {
            }
        }
        return "";
    }
}
